package kks;

import static robocode.util.Utils.normalRelativeAngleDegrees;
import java.awt.Color;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;

/**
 * The robot moves along the walls with its gun facing inwards and fires at any enemy it spots or
 * runs into. Modified from sample Walls robot (Contributors: Mathew A. Nelson, Flemming N. Larsen).
 * 
 * @author Kelli Sawai
 * 
 */
public class CounterAll extends Robot {

  // Indicates if there is an enemy robot there
  boolean peek;
  // Distance in pixels to move this robot
  double moveAmount;
  // Amount of degrees to turn the gun
  double gunTurnAmount;
  // Change directions
  int change = 0;
  // Lesser value of battlefield width or height
  double minLength;

  /**
   * Moves this robot around the outer edge of the battlefield in a counterclockwise motion with its
   * gun facing inwards.
   */
  public void run() {
    minLength = Math.min(getBattleFieldWidth(), getBattleFieldHeight());
    // set color of robot
    setBodyColor(Color.blue);
    setGunColor(Color.black);
    setRadarColor(Color.black);

    // Initialize to the maximum possible for this battlefield
    moveAmount = Math.max(getBattleFieldWidth(), getBattleFieldHeight());
    // Initialize peek to false
    peek = false;

    // Turn left to face a wall
    turnLeft(getHeading() % 90);
    // Move to wall
    ahead(moveAmount);
    // Set peek to true
    peek = true;

    // Turn the gun to turn left 90 degrees so it will face inwards.
    turnGunLeft(90);
    turnLeft(90);

    while (true) {
      if (change < 8) {
        // After turning, scan before moving ahead
        peek = true;
        // Move along the wall
        ahead(moveAmount);
        // out.println("moveAmount = " + moveAmount);

        // Don't scan before turning
        peek = false;

        // Turn to the next wall
        turnLeft(90);
        change++;
      }
      // Change direction of robots movement around the battlefield
      else if (change >= 6 && change < 12) {
        // After turning, scan before moving ahead
        peek = true;
        // Move along the wall
        back(moveAmount);
        // out.println("moveAmount = " + moveAmount);

        // Don't scan before turning
        peek = false;

        // Turn to the next wall
        turnRight(90);
        change++;
      }
      else {
        // Reset change back to 0
        change = 0;
      }
    }
  }

  /**
   * Turns gun and fires at enemy when it runs into it.
   * 
   * @param event Hit robot event set by the game
   */
  public void onHitRobot(HitRobotEvent event) {
    // Calculate amount of degrees to turn the gun. Taken from sample
    // Tracker robot.
    gunTurnAmount =
        normalRelativeAngleDegrees(event.getBearing() + (getHeading() - getRadarHeading()));
    turnGunRight(gunTurnAmount);
    fire(3);
    // Corrects gun to normal position after done firing
    turnGunLeft(gunTurnAmount);
  }

  /**
   * Turns and moves left when hit by enemy fire.
   * 
   * @param event Hit by bullet event set by the game
   */
  public void onHitByBullet(HitByBulletEvent event) {
    // Moves in a different direction when hit
    turnLeft(90);
    ahead(100);
    turnLeft(90);
    ahead(moveAmount);
  }

  /**
   * Fires at enemy robot when spotted.
   * 
   * @param event The scanned robot event set by the game
   */
  public void onScannedRobot(ScannedRobotEvent event) {

    int firePower = calculateFirePower(event.getDistance(), event.getBearing());

    fire(firePower);
    // Manually calls scan to ensure that the robot doesn't move if an enemy
    // is on the next wall
    if (peek) {
      scan();
    }

  }

  /**
   * Calculates the amount of power the bullet should be fired at proportional to the distance of
   * the enemy.
   * 
   * @param distance Distance between CounterAll and enemy robot
   * @param bearing Bearing of enemy robot
   * @return the bullet power
   */
  public int calculateFirePower(double distance, double bearing) {
    // out.println(minLength);
    // If the enemy is close to the opposite wall or far away, use less fire
    // power
    if (distance >= (minLength - 10) && (bearing != 180) && (bearing != 0)) {
      return 1;
    }
    else {
      return 3;
    }
  }
}
